<!--
 * Copyright ©
 * #  
 * @author: zw
 * @date: 2022-03-28 
 -->


<template>
  <div class="w-full h-full bg-yellow-100">
    <search />
    <panel @interactionDrawEvent="PanelInteractionDraw" @stopDraw="stopOperateDraw" @clearDraw="PanelClearDraw" @panelClick="panelClick" @measuresDraw="PanelMeasuresDraw" />
    <mousePosition />
    <popup ref="popRef" :map="map" :featureInfo="featureInfoPropert" />
  </div>
</template>

<script>
import eventBus, { FLY_DISTRICTS, FEATURE_EFFECT, SPACE_QUERY, RANDOM_POINT } from "./bus";
import Panel from "./components/Panel";
import mousePosition from "./components/MousePosition";
import popup from "./components/Popup";
import search from "./components/Search";
import { mouseposition, scaleline, interactionDrawFunc, __checkLayerVector, __checkInteractDraw, __findLayer, removeFeatures, Measures, getExent4, QuerySpace } from "./utils";
import { addBoundary, baiduXYZ, OSM, featureEffect, heatLayer, flyTo, FlyLine } from "./utils/layers";
import { fromLonLat, toPixel, toLonLat } from "./utils/transfrom";
import { district_polygon, dwar_style, wfs_point, flyTo_style } from "./utils/style";
import { getBoundary } from "@/api";
import wuhanCity from "./utils/wuhan";

var map;
export default {
  name: 'Maps',
  components: { Panel, mousePosition, popup, search },
  data() {
    return {
      map: null,
      interactiondraw: null,  //绘图交互
      DrawLayer: null,        //绘图
      DrawSource: null,       //绘图
      measureLayer: null,     //测量
      measureSource: null,    //测量
      spaceQueryLayer: null,  //查询
      flyLineLayer: null,     //飞线
      flyLineSource: null,    //飞线
      spaceQuery_interactiondraw: null, //查询交互
      spaceQuerySource: null, //查询
      CityBoundaryLayer: null,     // city-polygon
      CityBoundarySource: null,    // city-polygon
      featureLayer: null,     // server
      featureSource: null,    // server
      featureInfoPropert: {},
      catchFeatureNames: {}, // 缓存起来添加的名字，万一用的着
    };
  },

  mounted() {
    this.initMap();
    this.responseEvtBus();
    this.changeViewFeatures();
    addBoundary.call(this, map, wuhanCity, "wh_city");
  },

  methods: {
    initMap() {
      const view = new ol.View({ center: fromLonLat([114, 30]), zoom: 13 });
      map = new ol.Map({ target: this.$el, controls: [mouseposition()], view });
      const dblClickInteraction = map.getInteractions().getArray().find(interaction => interaction instanceof ol.interaction.DoubleClickZoom);
      map.removeInteraction(dblClickInteraction);
      map.addLayer(OSM);
      map.addControl(scaleline(map));
      this.map = map;
      map.on('click', evt => {
        const feature = map.forEachFeatureAtPixel(evt.pixel, feature => feature);
        if (!feature || !feature.id_) return this.$refs.popRef.popup && this.$refs.popRef.popup.setPosition(undefined);
        if (feature.getGeometry().getType() !== 'Point') return this.$refs.popRef.popup && this.$refs.popRef.popup.setPosition(undefined);
        const properties = feature.getProperties();
        delete properties.geometry;
        this.featureInfoPropert = properties;
        this.$refs.popRef.popup && this.$refs.popRef.popup.setPosition(toPixel(map, evt.pixel));
      });
      this.listenerDomStopevent();
    },
    async changeViewFeatures() {
      const url = "https://dzzb.hubgs.com:18090/geoserver/hbsddy/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=hbsddy%3Azk&maxFeatures=5000&outputFormat=application%2Fjson";
      const result = await fetch(url, { method: 'get' }).then(response => response.json());
      featureEffect.call(this, map, result);
    },
    PanelInteractionDraw(params) {
      const { type, freeDraw } = params;
      if (this.interactiondraw) map.removeInteraction(this.interactiondraw);
      const { layer, source } = __checkLayerVector.call(this, map, "DrawLayer", "DrawSource");
      layer.setZIndex(11);
      layer.setStyle(dwar_style);
      if (!freeDraw) this.interactiondraw = interactionDrawFunc(source, params);
      else this.interactiondraw = freeDraw(source, type);
      map.addInteraction(this.interactiondraw);
    },
    panelClick({ type }) {
      const view = map.getView();
      let zoom = view.getZoom();
      switch (type) {
        case "zoomIn":
          map.getView().setZoom(zoom + 0.5);
          break;
        case "zoomOut":
          map.getView().setZoom(zoom - 0.5);
          console.log(getExent4(map));
          break;
        case "reset":
          const extent = [12712127.839937367, 3552349.4999768916, 12736792.172894511, 3564386.2083002483];
          const resolution = map.getView().getResolutionForExtent(extent, map.getSize());
          map.getView().setResolution(resolution);
          map.getView().setCenter(ol.extent.getCenter(extent));
          break;
        default:
          break;
      }
    },
    PanelMeasuresDraw(type) {
      if (type === "clearMeasures") {
        const layer = __findLayer(map, "name", "measureLayer");
        if (!layer) return;
        layer.getSource().clear();
        map.getOverlays().clear();
        return;
      };
      this.stopOperateDraw();
      const { layer, source } = __checkLayerVector.call(this, map, "measureLayer", "measureSource");
      layer.setZIndex(11);
      Measures.measures(map, type, source);
    },
    PanelClearDraw() {
      const layer = __findLayer(map, "name", "DrawLayer");
      if (!layer) return;
      layer.getSource().clear();
      map.removeInteraction(this.interactiondraw);
      map.removeLayer(this.DrawLayer);
      this.DrawSource = null;
      this.DrawLayer = null;
    },
    async boundary(city) {
      const params = {
        keywords: city,
        subdistrict: 0,
        extensions: "all"
      }
      const { status, info, districts, } = await getBoundary(params);
      if (!status) return this.$message.error(info);
      const { catchFeatureNames } = this;
      removeFeatures(this.CityBoundarySource, catchFeatureNames.name);
      districts.forEach((item, index) => {
        const { center, name, level, polyline } = item; // level: country:国家 province:省份（直辖市会在province和city显示）city:市（直辖市会在province和city显示） district:区县 street:街道
        const id = districts.length <= 1 ? name : name + index;
        catchFeatureNames.name = name;
        addBoundary.call(this, map, polyline, id, district_polygon);
      });
      const { center } = districts[0];
      let pos = center.split(",");
      pos = pos[0] < 114 ? districts[1].center.split(",") : pos; // 高德地图存在一个经纬度中心的坑、判断过滤一下
      flyTo(map, fromLonLat(pos), function () { });
    },
    responseEvtBus() {
      eventBus.$on(FLY_DISTRICTS, city => {
        this.boundary(city);
      });
      eventBus.$on(FEATURE_EFFECT, type => {
        let layer;
        const source = this.featureSource;
        switch (type) {
          case "要素图层":
            layer = __findLayer(map, "name", "heat-map");
            map.removeLayer(layer);
            map.addLayer(this.featureLayer);
            break;

          case "热力图层":
            layer = __findLayer(map, "name", "featureLayer");
            map.removeLayer(layer);
            layer = heatLayer(source);
            layer.setZIndex(10);
            layer.setStyle(wfs_point);
            map.addLayer(layer);
            break;

          default:
            break;
        }
      });
      eventBus.$on(SPACE_QUERY, async (shape) => {
        this.stopOperateDraw();
        const { layer, source } = __checkLayerVector.call(this, map, "spaceQueryLayer", "spaceQuerySource");
        layer.setZIndex(11);
        const draw = __checkInteractDraw.call(this, map, 'spaceQuery_interactiondraw', 'spaceQuerySource', shape);
        const result = await QuerySpace.selectionPolygon(map, source, draw, { a: 1, b: 2 });
        const { data } = result;
        const polyline = data.map(item => toLonLat(item));
        console.log(JSON.stringify(polyline));
        map.removeInteraction(draw);
      });
      eventBus.$on(RANDOM_POINT, (Info) => {
        this.$refs.popRef.popup && this.$refs.popRef.popup.setPosition(undefined);
        this.flyLineLayer && this.flyLineLayer.getSource().clear();
        const { layer, source } = new FlyLine(map, Info.坐标x, Info.坐标y);
        this.flyLineLayer = layer;
        this.flyLineSource = source;
      })
    },
    listenerDomStopevent() {
      const stopevent = document.querySelector('.ol-overlaycontainer-stopevent');
      stopevent && stopevent.addEventListener('click', this.domStopeventEvtFunc);
    },
    domStopeventEvtFunc(evt) {
      const _target = evt.target;
      if (_target.className.includes('clear-drawing')) {
        const layer = __findLayer(map, "name", "spaceQueryLayer");
        layer.getSource().clear();
        map.removeLayer(layer);
        this.spaceQueryLayer = null;
        this.spaceQuerySource = null;
        const stopevent = document.querySelectorAll('.close-drawing-tip');
        const parent = (stopevent.length && stopevent[0].parentNode) || [];
        if (stopevent.length) {
          for (let i = 0; i < stopevent.length; i++) {
            parent.removeChild(stopevent[i]);
          }
        }
      }
    },
    stopOperateDraw() {
      Measures.removeInteraction(map);
      if (this.interactiondraw) map.removeInteraction(this.interactiondraw);
      if (this.spaceQuery_interactiondraw) map.removeInteraction(this.spaceQuery_interactiondraw);
    }
  },
  beforeDestroy() {
    eventBus.$off([FLY_DISTRICTS, FEATURE_EFFECT, SPACE_QUERY]);
    const stopevent = document.querySelector('.ol-overlaycontainer-stopevent');
    stopevent && stopevent.removeEventListener('click', this.domStopeventEvtFunc);
  },
  //  End
}

</script>

<style lang="scss" scoped>

  /deep/ {
    .ol-tooltip {
      position: relative;
      background: rgba(0, 0, 0, 0.5);
      border-radius: 4px;
      color: white;
      padding: 4px 8px;
      opacity: 0.7;
      white-space: nowrap;
      font-size: 12px;
    }
    .ol-tooltip-measure {
      opacity: 1;
      font-weight: bold;
    }
    .ol-tooltip-static {
      background-color: #ffcc33;
      color: black;
      border: 1px solid white;
    }
    .ol-tooltip-measure:before,
    .ol-tooltip-static:before {
      border-top: 6px solid rgba(0, 0, 0, 0.5);
      border-right: 6px solid transparent;
      border-left: 6px solid transparent;
      content: "";
      position: absolute;
      bottom: -6px;
      margin-left: -7px;
      left: 50%;
    }
    .ol-tooltip-static:before {
      border-top-color: #ffcc33;
    }
    .close-drawing-tip {
      background-color: #c0c4cc;
      border-radius: 4px;
      text-align: center;
    }
    .clear-drawing {
      display: inline-block;
      cursor: pointer;
      font-size: 12px;
      width: 18px;
      height: 12px;
      z-index: 999;
      user-select: none;
      color: white;
      font-weight: bold;
    }
  }

</style>